%token Name ("name") : Name
%token QuoteLiteral ("quote literal") : Constant

%xstart SQSTRING

%define pg.parser.usings (
    System,
    System.Collections.Generic,
    System.Collections.ObjectModel,
    System.Diagnostics,
    System.IO,
    System.Linq,
    System.Numerics,
    System.Text,
    ParserGenerator.CharacterMapping,
    ParserGenerator.CodeGeneration,
    ParserGenerator.Collections,
    ParserGenerator.Directives,
    ParserGenerator.Exceptions,
    ParserGenerator.Expressions,
    ParserGenerator.Extensions,
    ParserGenerator.GrammarConstruction,
    ParserGenerator.Input,
    ParserGenerator.LexicalAnalysis,
    ParserGenerator.LexicalDeclarations,
    ParserGenerator.LexicalExpressions,
    ParserGenerator.Output,
    ParserGenerator.SyntacticDeclarations,
    ParserGenerator.SyntacticExpressions,
    ParserGenerator.Statements,
    ParserGenerator.TypeDeclarations,
    ParserGenerator.TypeExpressions,
)

%define pg.parser.classname ProgramDescriptionParser
%define pg.parser.namespace ParserGenerator.Statements

SyntacticExpression:
    Empty
    String (value : Constant)
    NameReference (name : Name)
    Kleene (operand : SyntacticExpression, useBrackets : bool)
    Optional (operand : SyntacticExpression, useBrackets : bool)
    Positive (operand : SyntacticExpression, useBrackets : bool)
    Sequence (operand : SyntacticExpression, nullable : bool, separator : Constant)
    Concat (left : SyntacticExpression, right : SyntacticExpression)
    Union (left : SyntacticExpression, right : SyntacticExpression)
    attributes! (context! : SourceContext?)

ISyntacticExpressionWriter.Write(n : SyntacticExpression, writer : IndentedWriter, d : int)

%%

lower  = ['a'-'z']
upper  = ['A'-'Z']
digit  = ['0'-'9']
letter = lower | upper | '_'
name   = letter (letter | digit)*

non_line_terminator = [^ '\n' '\v' '\f' '\r' '\x85' '\u2028' '\u2029']

name                =>: ScanNameValue();      yield Name

"\'"     =>: BeginString(SQSTRING, True)

<SQSTRING>:
    "\'" =>: EndString(); yield QuoteLiteral
<SQSTRING>:
    non_line_terminator =>: AppendTokenString()

<SQSTRING>:
    default =>: raise UnterminatedString()
